package edu.ncsu.csc.itrust.dao.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import edu.ncsu.csc.itrust.DBUtil;
import edu.ncsu.csc.itrust.beans.InstructionBean;
import edu.ncsu.csc.itrust.beans.OfficeVisitBean;
import edu.ncsu.csc.itrust.beans.loaders.InstructionBeanLoader;
import edu.ncsu.csc.itrust.dao.DAOFactory;
import edu.ncsu.csc.itrust.exception.DBException;

/**
 * DAO for Instructions associated with Office Visits
 * @author Patrick Finegan 
 *
 */
public class OfficeVisitInstructionDAO {

	/** Obligatory parent object */
	private DAOFactory factory;
	/** Bean Loader */
	private InstructionBeanLoader bload = new InstructionBeanLoader();
	/** Office Visit DAO for setting Office Visit time */
	private OfficeVisitDAO ovDAO;
	
	/**
	 * The typical constructor.
	 * @param factory The {@link DAOFactory} associated with this DAO, which is used for obtaining SQL connections, etc.
	 */
	public OfficeVisitInstructionDAO(DAOFactory factory) {
		this.factory = factory;
		ovDAO = factory.getOfficeVisitDAO();
	}
	
	/**
	 * Adds an Instruction to an office visit.
	 * 
	 * @param instruct -- InstructionBean with new instruction
	 * @return The unique ID of the code that was added.
	 * @throws DBException
	 */
	public long addInstruction(InstructionBean ibean) throws DBException {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = factory.getConnection();
			ps = conn.prepareStatement("INSERT INTO ovinstructions (MID,PID," +
					"descriptName, url, comments, ovID, modTime) VALUES (?,?,?,?,?,?,?)");
			bload.loadParameters(ps, ibean);
			ps.executeUpdate();
			return DBUtil.getLastInsert(conn);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DBException(e);
		} finally {
			DBUtil.closeConnection(conn, ps);
		}
	}
	
	/**
	 * Removes a given instruction.
	 * 
	 * @param instructionID The unique ID of the instruction.
	 * @throws DBException
	 */
	public void removeInstruction(long instructionID) throws DBException {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = factory.getConnection();
			ps = conn.prepareStatement("DELETE FROM ovinstructions WHERE ID=?");
			ps.setLong(1, instructionID);
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DBException(e);
		} finally {
			DBUtil.closeConnection(conn, ps);
		}
	}
	
	/**
	 * Edits an existing instruction bean.
	 * 
	 * @param ibean The newly updated instruction bean.
	 * @return A long indicating the ID of the newly updated instruction bean.
	 * @throws DBException
	 */
	public long editInstruction(InstructionBean ibean) throws DBException {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = factory.getConnection();
			String statement = "UPDATE ovinstructions " +
				"SET descriptName=?, url=?, comments=?, modTime=? WHERE ID=?";
			ps = conn.prepareStatement(statement);
			ps.setString(1, ibean.getDescriptName() );
			ps.setString(2, ibean.getURL() );
			ps.setString(3, ibean.getComments() );
			ps.setString(4, new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()) );
			ps.setLong(5, ibean.getInstructID() );
			ps.executeUpdate();
			return DBUtil.getLastInsert(conn);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DBException(e);
		} finally {
			DBUtil.closeConnection(conn, ps);
		}
	}
	
	/**
	 * Returns a particular instruction set given a PID
	 * 
	 * @param PID The unique PID of the patient.
	 * @return An InstructionBean list with the specifics for the Instructions.
	 * @throws DBException
	 */
	public List<InstructionBean> getInstructionForPatient(long patientID) throws DBException {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = factory.getConnection();
			ps = conn.prepareStatement("SELECT * FROM ovinstructions WHERE PID = ?");
			ps.setLong(1, patientID);
			ResultSet rs = ps.executeQuery();
			return bload.loadList(rs);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DBException(e);
		} finally {
			DBUtil.closeConnection(conn, ps);
		}
	}
	
	/**
	 * Returns a particular instruction set given a Office Visit ID
	 * 
	 * @param ovID -- the unique id of the office visit
	 * @return An InstructionBean list with the specifics for the Instructions.
	 * @throws DBException
	 */
	public List<InstructionBean> getInstructionForOfficeVisit(long ovID) throws DBException {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = factory.getConnection();
			ps = conn.prepareStatement("Select * From ovinstructions Where ovID = ?");
			ps.setLong(1, ovID);
			ResultSet rs = ps.executeQuery();
			return bload.loadList(rs);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new DBException(e);
		} finally {
			DBUtil.closeConnection(conn, ps);
		}
	}
}
